from peewee import *
from playhouse.mysql_ext import MySQLConnectorDatabase
from playhouse.pool import PooledMySQLDatabase
from psycopg2.extensions import ISOLATION_LEVEL_SERIALIZABLE

# 代表和数据库之间的连接，功能：
# 1、打开/关闭连接
# 2、执行查询
# 3、管理事务（包括SavePoint，但是savepoint很少用到）
# 4、读取表格、列、索引、约束的元信息

# peewee 支持SQLite、MySQL、Postgres，每个数据库类都有一些自己特有的配置项
# 默认是autoconnect的
# db对象是线程安全的

# db = MySQLConnectorDatabase('jiatuedudb', user="root", password="root", host="localhost", port=3306)

# 数据库连接池
# 默认情况下，应用程序需要做的就是确保连接在完成后关闭，并且它们将返回到池中。对于web应用程序，
# 这通常意味着在请求开始时，您将打开一个连接，当您返回响应时，您将关闭该连接
# timeout参数的意思是当连接池已经满了，此时又需要申请连接，就block等待，这里设置为5秒，意思是5秒内拿不到连接，就报错，设置为0表示一直等待下去（这个不现实，没啥意义，不应该设置为0）
db = PooledMySQLDatabase('jiatuedudb', user="root", password="3099Amm32$=!", host="118.31.33.86", port=3306, max_connections=256,
                         stale_timeout=300, timeout =5)

# 关于事务，peewee提供了几种接口，最常见的是调用 db.atomic()，也支持嵌套事务，atomic标记的代码块会在事务中执行，如果代码执行报错那么就会回滚，否则就会自动提交事务；
# http://docs.peewee-orm.com/en/latest/peewee/database.html#managing-transactions
# 下面是一段演示代码
# with db.atomic() as transaction:  # Opens new transaction.
#     try:
#         save_some_objects()
#     except ErrorSavingData:
        # Because this block of code is wrapped with "atomic", a new transaction will begin automatically after the call to rollback().
        # transaction.rollback()
        # error_saving = True

    # create_report(error_saving=error_saving)
    # Note: no need to call commit. Since this marks the end of the wrapped block of code, the `atomic` context manager will automatically call commit for us.
    # 不需要手动调用commit，代码最后结尾，atomic这个上下文管理器会自动调用commit

# atomic的2种用法：with db.atomic as tx  另外一种做法是：@db.atomic()，这个是一个装饰器

# 连接数据库，返回True，不要重复调用connect
# db.connect(reuse_if_open=True)
# 关闭数据库连接
# db.close()
# 判断是否关闭
# db.is_closed()


# autocommit，默认情况下，peewee中autocommit是自动提交的，所以任何在一段事务之外的sql代码都会在一个新的、它自己的事务中执行，如果要把所有sql代码都放在一个事务中，那很简单呀，
# 把这些代码写在一个函数中，然后用@db.atomic()装饰器装饰一下就行了，这可以覆盖所有场景！但是如果犯贱，非要自己提交，那么就用db.manual_commit()、db.begin()、db.rollback()、db.commit()，
# 一般根本没人这样做！

class BaseModel(Model):
    class Meta:
        database = db
